package cn.iborder.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import com.jfinal.i18n.Res;
import com.jfinal.log.Log;

import cn.iborder.configurator.HttpSessionConfigurator;
import cn.iborder.core.ResMap;
import cn.iborder.core.ResPool;
import cn.iborder.entity.Machine;
import cn.iborder.utils.PubUtil;
import cn.iborder.utils.SshClient;
import cn.iborder.utils.TrcLog;
import cn.iborder.utils.WebSshUtil;

@ServerEndpoint(value = "/ws", configurator = HttpSessionConfigurator.class)
public class WebSocketController {
	private static Log log = TrcLog.getLogFile();
	private Machine currentMachine = null;
	private SshClient sshClient = null;
	private List<Session> sessionList = null;
	
	private Session wsSession;
	private HttpSession httpSession;
	private static HashMap<String, WebSocketController> hashMap;

	static {
		hashMap = new HashMap<>();
	}
	
	@OnOpen
	public void onOpen(Session wsSession, EndpointConfig config) {
		log.info("[WebSocketHandler]onOpen");
		this.wsSession = wsSession;
		this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
		log.info("[WebSocketHandler]判断用户登录状态");
		if (!PubUtil.trim(httpSession.getAttribute("loginuser")).equals("")
				&& PubUtil.trim(httpSession.getAttribute("loginstatus")).equals("success")) {
			// 已登录
			hashMap.put(httpSession.getId(), this);
			currentMachine = (Machine) this.httpSession.getAttribute("currentMachine");

			if (currentMachine != null) {
				
				if (sessionList == null)
					sessionList = new ArrayList<>();
				
				//添加回话到当前集合
				sessionList.add(wsSession);
				//添加到集合中
				//userSocketSessionMap.put(user.getId(), sessionList);
				log.info("[WebSocketHandler]connect...");
				
				//连接机器
				sshConnect(wsSession, currentMachine, 10086);
			}
		} else {
			// 非法
			sendBinaryMsg(wsSession,"Login timeout, please login again, close the connection.");
			try {
				wsSession.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	@OnClose
	public void onClose(Session session) {
		log.info("[WebSocketHandler]onClose");
		if (sshClient != null) {
			sshClient.disconnect();
		}
	}

	@OnMessage
	public void onMessage(String requestJson, Session session) {
		log.info("[WebSocketHandler.onMessage]requestJson:" + requestJson);
		try {
			//当客户端不为空的情况
			if (sshClient != null) {
				//写入前台传递过来的命令，发送到目标服务器上
				log.info("[WebSocketHandler.onMessage]sessionStatus:"+sshClient.getSessStatus());
				log.info("[WebSocketHandler.onMessage]channelStatus:"+sshClient.getChannelStatus());
				//sshClient.openChannel();
				
				String cmd = "";
				if (requestJson.contains("{\"resize\":")) {
					
					cmd = requestJson.substring(11, (requestJson.length()-2));
					int term_width_characters = Integer.parseInt(cmd.split(",")[0]);
					int term_height_characters = Integer.parseInt(cmd.split(",")[1]);
					log.info("[WebSocketHandler]resize:"+term_width_characters+","+term_height_characters);
					
					sshClient.setPtySize(term_width_characters, term_height_characters);
				}else{
					//限制每次发送数据最大长度默认64
					//int inShellDataSize = PropKit.getInt("inShellDataSize");
					int inShellDataSize = ResPool.getConfigPool().getInt("inShellDataSize");
					for(int i=0; i<Math.ceil((requestJson.length()*1.0)/inShellDataSize); i++){
						sshClient.write(new String(requestJson.substring(i*inShellDataSize, requestJson.length()>(i+1)*inShellDataSize?(i+1)*inShellDataSize:requestJson.length()).getBytes(), "UTF-8"));
					}
					//sshClient.write(new String(requestJson.getBytes(), "UTF-8"));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			sendBinaryMsg(session,"An error occured, websocket is closed.");
			try {
				session.close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}

	private static void sendTextMsg(Session session, String msg) {
		try {
			session.getBasicRemote().sendText(msg);
		} catch (IOException e) {
			try {
				String message = "has been disconnected.";
				sendTextMsg(session, message);
				session.close();
			} catch (IOException e1) {
				// Ignore
			}
		}
	}
	
	private static void sendBinaryMsg(Session session, ByteBuffer msg) {
		session.getAsyncRemote().sendBinary(msg);
	}
	
	public static void sendBinaryMsg(Session session, String msg){
		try {
			if (WebSshUtil.getEncoding(msg.toString()).equals("ISO-8859-1")){
				msg = new String(msg.toString().getBytes("ISO-8859-1"),"UTF-8");
			}else{
				msg = new String(msg.toString().getBytes("gb2312"),"UTF-8");
			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		log.info("[WebSocketHandler]sendBinaryMsg["+msg.getBytes().length+"]:"+new String(msg.getBytes()));
		synchronized (session.getAsyncRemote()) {
			session.getAsyncRemote().sendBinary(ByteBuffer.wrap(msg.getBytes()));
		}
		msg = msg.replaceAll("\r", "");
		msg = msg.replaceAll("\n", "");
		if (msg.equals("logout")) {
			try {
				session.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 连接服务端
	 * @param session
	 * @param machine
	 * @param spkey
	 */
	private void sshConnect(Session session, Machine machine, Integer spkey) {
		
		sshClient = new SshClient();
		
		try {
			sendBinaryMsg(session,"Try to connect...\r");
			
			//连接服务器
			sshClient.connect(machine);
			sshClient.getShellOutput(session);
		} catch (Exception e) {
			try {
				session.close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
	}
	
}
